#include "channel.h"

Channel::Channel(qreal E, qreal SNRdB, QObject *parent) :
  QObject(parent),
  m_E(E)
{
  setSNRdB(SNRdB);
}

// задать соотношение сигнал-шум
void Channel::setSNRdB(const qreal SNRdB) {
  // SNR = E/No
  // SNR - signal to noise ratio (отношение сигнал/шум)
  qreal SNR    = qPow( 10.0, (SNRdB / 10.0) ); // перевод из децибел
  qreal noiseD = m_E / (SNR * 2.0);            // дисперсия шума, для БГШ D = N0/2
  m_sigma      = qSqrt(noiseD);                // среднее квадратичное отклонение
}

// генератор случайных числе [0.0; 1.0]
// постусловие: результат в пределах [0.0; 1.0]
inline qreal Channel::rnd() {
  qreal res = qrand() / (qreal)RAND_MAX; // от 0.0 до 1.0

#ifdef ERRS
  if (res > 1.0 || res < 0.0) {
    error("Channel::rnd(): выдает числа за пределами отрезка [0.0; 1.0].");
  }
#endif

  return res;
}

// числа распределенные по нормальному закону
inline qreal Channel::randn() {
  qreal res = qSqrt(  -/*2.0 **/ qLn( rnd() )  ) * qCos( 2.0 * M_PI * rnd() );
  return res;
}

// шум в виде сигнальной точки
inline QPointF Channel::noise() {
  QPointF res( randn(), randn() );
  res = m_sigma * res; // + QPointF(M, M), но M = 0
  return res;
}

// добавить шум к входным сигналам
QVector<QPointF> Channel::addNoise(QVector<QPointF> s) {
  for (int i = 0; i < s.size(); ++i) {
    s[i] = s[i] + noise();
  }

  return s;
}
